package org.quickjsf.core.annotations;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import javax.faces.convert.Converter;
import javax.faces.convert.DateTimeConverter;

import org.apache.commons.lang3.StringUtils;
import org.quickjsf.common.util.DomainUtil;
import org.quickjsf.common.util.FacesUtil;
import org.quickjsf.core.base.QuickJsfContainer;
import org.quickjsf.core.datamodel.OptionType;
import org.quickjsf.core.base.viewmodel.vo.ColumnModel;

public class ColumnModelHandler {
	
	public static void handlerColumnModel(Class<? extends Object>[] domainClasses, 
			Map<String, List<ColumnModel>> columnModelMap, Map<String, Map<String, List<OptionType>>> optionTypeMap) throws Exception {
		for (Class<? extends Object> cls : domainClasses) {
			int order = 0;
			Method[] declaredFields = cls.getDeclaredMethods();
			for (Method method : declaredFields) {
				org.quickjsf.core.annotations.ColumnModel annotationColumnModel 
					= method.getAnnotation(org.quickjsf.core.annotations.ColumnModel.class);
				
				if (method.getName().startsWith("get") && null != annotationColumnModel) {
					
					org.quickjsf.core.annotations.OptionType[] optionTypes = annotationColumnModel.optionTypes();
					if (columnModelMap.get(cls.getSimpleName()) == null) {
						columnModelMap.put(cls.getSimpleName(), new ArrayList<ColumnModel>());
					} 
					order++;
					
					Converter converter = null;
					ColumnModel columnModel = null;
					String field = StringUtils.uncapitalize(method.getName().substring(3));
					
					//设置转换器
					if (!StringUtils.isEmpty(annotationColumnModel.converter())) {
						String annotationConverter = annotationColumnModel.converter().trim();
						//去除首尾的'{' 和 '}'
						annotationConverter = annotationConverter.substring(1, annotationConverter.length()-1);
						String[] converterStr = annotationConverter.split(",");
						for (String converterWrapper : converterStr) {
							String[] wrapper = converterWrapper.split("=");
							String key = wrapper[0].trim();
							String value = wrapper[1].trim();
							
							if (key.toUpperCase().equals("CONVERTID")) {
								converter = FacesUtil.getApplication().createConverter(value);
								//设置DateTimeConverter的Locale、TimeZone
								if (converter instanceof DateTimeConverter) {
									((DateTimeConverter)converter).setLocale(QuickJsfContainer.locale);
									((DateTimeConverter)converter).setTimeZone(TimeZone.getDefault());
								}
							} else {
								DomainUtil.setFieldValue(converter, key, value);
							}
						}
					}
					
					if (annotationColumnModel.order() > 0 && columnModelMap.get(cls.getSimpleName()).size() >= annotationColumnModel.order()) {
						columnModel = new ColumnModel(annotationColumnModel.value(),
								field, optionTypes.length > 0, annotationColumnModel.order(), converter);
						columnModelMap.get(cls.getSimpleName()).add(annotationColumnModel.order()-1, columnModel);
					} else {
						columnModel = new ColumnModel(annotationColumnModel.value(),
								field, optionTypes.length > 0, annotationColumnModel.order() == 0 ? (order) : annotationColumnModel.order(), converter);
						columnModelMap.get(cls.getSimpleName()).add(columnModel);
					}
					
					if (optionTypes.length > 0) {
						if (optionTypeMap.get(cls.getSimpleName()) == null) {
							optionTypeMap.put(cls.getSimpleName(), new HashMap<String, List<OptionType>>(5));
							
						} 
						if (optionTypeMap.get(cls.getSimpleName()).get(field) == null) {
							optionTypeMap.get(cls.getSimpleName()).put(field, new ArrayList<OptionType>(8));
							
						}
						for (org.quickjsf.core.annotations.OptionType optionType : optionTypes) {
							optionTypeMap.get(cls.getSimpleName()).get(field).add(new OptionType(optionType.name(),
									method.getReturnType().getConstructor(String.class).newInstance(optionType.value()) ));
						}
						columnModel.setOptionTypes(optionTypeMap.get(cls.getSimpleName()).get(field));
					}
				} 
			}
			if (columnModelMap.get(cls.getSimpleName()) != null) {
				Collections.sort(columnModelMap.get(cls.getSimpleName()), ColumnModel.getComparator());
			}
		}
	}
}
